package remote

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net"
	"strings"
	"time"

	D "gitee.com/dark.H/go-remote-repl/datas"
)

type ApiConn struct {
	con net.Conn
	// reader        io.ReadCloser
	GloablError   error
	Target        string
	LastRead      time.Time
	readDeadline  time.Time
	writeDeadline time.Time
	msg           chan string
}

func NewApiConn(con net.Conn, firstOper ...string) (api *ApiConn) {
	api = new(ApiConn)
	api.con = con
	api.Target = strings.SplitN(con.RemoteAddr().String(), ":", 2)[0]
	api.msg = make(chan string)
	if firstOper != nil {
		api.SendMsg(firstOper[0])
	} else {
		api.SendMsg("PASS")
	}
	return
}

func (api *ApiConn) Close() (err error) {
	if api.con != nil {
		err = api.con.Close()
	}

	return
}

func (api *ApiConn) Read(buf []byte) (n int, err error) {
	bufs := <-api.msg
	n = len(bufs)
	if len(bufs) < cap(buf) {
		copy(buf, []byte(bufs))

	} else {
		buf = append(buf, []byte(bufs)...)
	}
	return
}

func (api *ApiConn) Write(buf []byte) (n int, err error) {
	var msg string
	if bytes.HasPrefix(buf, []byte("list:")) {
		msg, err = api.Choose(string(buf))
	} else if bytes.HasPrefix(buf, []byte("repl:")) {
		msg, err = api.Repl(string(buf))
	} else if bytes.HasPrefix(buf, []byte("repls:")) {
		msg, err = api.ReplJ(string(buf))
	} else if bytes.HasPrefix(buf, []byte("replf:")) {
		var funck string
		msg, funck, err = api.ReplF(string(buf))
		if err != nil {
			return
		}
		api.ToggleFunction(funck, msg)
		n = len(buf)
		return
	} else if bytes.HasPrefix(buf, []byte("config:")) {
		D.NewMemDBCli(api.con)
	} else {
		data := make(map[string]interface{})
		if err := json.Unmarshal(buf, &data); err != nil {
			fmt.Println(string(buf))
		} else {
			fmt.Println(D.Data(data))
		}
		return len(buf), nil
	}
	if err != nil {
		return
	}
	api.msg <- msg
	n = len(buf)
	return
}

func (api *ApiConn) LocalAddr() net.Addr {
	w, _ := net.ResolveIPAddr("tcp", "127.0.0.1")
	return w
}

func (api *ApiConn) RemoteAddr() net.Addr {
	w, _ := net.ResolveIPAddr("tcp", api.Target)
	return w
}

func (api *ApiConn) SetDeadline(t time.Time) (err error) {
	api.readDeadline = t
	api.writeDeadline = t
	return
}

func (api *ApiConn) SetReadDeadline(t time.Time) (err error) {
	api.readDeadline = t
	return
}

func (api *ApiConn) SetWriteDeadline(t time.Time) (err error) {
	api.writeDeadline = t
	return
}
